/***************************************************************************
      File Name:  ProcessHelpers.cs
   File Created:  Wednesday, June 13th 2007
      Copyright:  (C) 2007 by Darko Matesic
          Email:  darko.matesic@yahoo.com
 ***************************************************************************/

using System;
using System.Diagnostics;
using System.Runtime.InteropServices;
using System.Threading;
using System.Reflection;
using System.Text;

namespace CallerID.Helpers
{
    public class ProcessHelpers
    {

        private static Mutex instance_mutex = null;
        private static bool instance_mutex_owned = false;
        public static bool PreviousInstanceExists(bool activatePreviousInstance)
        {
            string assemblyName = Assembly.GetEntryAssembly().GetName().Name;
            if(instance_mutex == null)
                instance_mutex = new Mutex(true, assemblyName + "_MUTEX_", out instance_mutex_owned);
            if(instance_mutex_owned == false && activatePreviousInstance) {
                Process currentProcess = Process.GetCurrentProcess();
                foreach(Process process in Process.GetProcessesByName(assemblyName)) {
                    if(currentProcess.Id != process.Id) {
                        IntPtr hWnd = process.MainWindowHandle;
                        if(IsIconic(hWnd)) ShowWindowAsync(hWnd, SW_RESTORE);
                        SetForegroundWindow(hWnd);
                        break;
                    }
                }
            }
            return (instance_mutex_owned == false);
        }

        public static void DisposeCurrentInstance()
        {
            if(instance_mutex != null) {
                instance_mutex.ReleaseMutex();
                instance_mutex = null;
            }
        }

        [DllImport("user32.dll")]
        [return: MarshalAs(UnmanagedType.Bool)]
        private static extern bool SetForegroundWindow(IntPtr hWnd);
        [DllImport("user32.dll")]
        [return: MarshalAs(UnmanagedType.Bool)]
        private static extern bool ShowWindowAsync(IntPtr hWnd, int nCmdShow);
        [DllImport("user32.dll")]
        [return: MarshalAs(UnmanagedType.Bool)]
        private static extern bool IsIconic(IntPtr hWnd);

        private const int SW_RESTORE = 9;

        /// <summary>
        /// Finds process with given executable name.
        /// </summary>
        public static Process FindProcess(string applicationExecutable, bool partialName)
        {
            if(applicationExecutable == null || applicationExecutable.Length == 0) return null;
            try {
                string applicationExecutableUpper = applicationExecutable.ToUpper();
                foreach(Process process in Process.GetProcesses()) {
                    try {
                        if(partialName) {
                            if(process.MainModule.FileName.ToUpper().EndsWith(applicationExecutableUpper)) return process;
                        } else {
                            if(process.MainModule.FileName.ToUpper() == applicationExecutableUpper) return process;
                        }
                    } catch { }
                }
            } catch { }
            return null;
        }


        /// <summary>
        /// Executes specified filenName.
        /// </summary>
        public static string Execute(string fileName, string workingDirectory, string arguments, bool hideWindow, bool returnOutput)
        {
            ProcessStartInfo info = new ProcessStartInfo(fileName);
            info.WorkingDirectory = workingDirectory;
            info.Arguments = arguments;
            if(hideWindow) {
                info.WindowStyle = ProcessWindowStyle.Hidden;
                info.CreateNoWindow = true;
            }
            info.UseShellExecute = false;
            info.ErrorDialog = false;
            info.RedirectStandardOutput = true;
            if(returnOutput) return ProcessOutputData.StartProcess(info);
            Process process = Process.Start(info);
            process.WaitForExit();
            return "";
        }

        /// <summary>
        /// Helper private class for reading process output.
        /// </summary>
        private class ProcessOutputData
        {
            public static string StartProcess(ProcessStartInfo info)
            {
                ProcessOutputData processOutputData = new ProcessOutputData();
                Process process = new Process();
                process.OutputDataReceived += new DataReceivedEventHandler(processOutputData.OutputDataReceived);
                process.StartInfo = info;
                process.Start();
                process.BeginOutputReadLine();
                process.WaitForExit();
                return processOutputData.output.ToString();

            }
            private ProcessOutputData()
            {
            }

            private StringBuilder output = new StringBuilder();

            public void OutputDataReceived(object sender, DataReceivedEventArgs e)
            {
                output.AppendLine(e.Data);
            }
        }
    }
}
